package cn.rengy.auth.jwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.SecretKey;

/**
 * JWT包含两部分：header和payload
 * JWS：签名的JWT，任何人都能看到数据，签名只确保数据没有被篡改
 * JWE：完全加密的jwt
 */
@Slf4j
public class JwtUtils {

//    private static ObjectMapper objectMapper=null;
//    static{
//        objectMapper=objectMapper();
//    }


    //private static SignatureAlgorithm signatureAlgorithm=SignatureAlgorithm.HS256;//指定签名的时候使用的签名算法

//    private static ObjectMapper objectMapper(){
//        ObjectMapper objectMapper=new ObjectMapper();
//        /**
//         * 如果是作为api返回结果，不需要反序列化时：不设置activateDefaultTyping或者使用EXISTING_PROPERTY。
//         * 如果作为缓存等，需要反序列化时：一般使用 WRAPPER_ARRAY、WRAPPER_OBJECT、PROPERTY(@class)中的一种。如果不指定则默认使用的是WRAPPER_ARRAY。
//         */
//        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
//        // 指定序列化输入的类型，类必须是非final修饰的，final修饰的类，比如String,Integer等会跑出异常
//        //objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
//
//        SimpleModule simpleModule = new SimpleModule();
//        simpleModule.addSerializer(new NullValueSerializer(null));
//        simpleModule.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE);
//        simpleModule.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
//        simpleModule.addSerializer(Duration.class, DurationSerializer.INSTANCE);
//        simpleModule.addDeserializer(Duration.class, DurationDeserializer.INSTANCE);
//        objectMapper.registerModule(simpleModule);
//        //指定要序列化的域，field,get和set,以及修饰符范围，ANY是都有包括private和public
//        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);//反序列化时没有set方法会报错
//        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);//忽略空值
//        return objectMapper;
//    }
    public static String create(Claims claims, SecretKey key){
        return Jwts.builder()
                //.compressWith(Jwts.ZIP.DEF)//压缩减少体积

                .claims(claims)

                //.json(new JacksonSerializer(objectMapper))

                .signWith(key).compact()
                //数字签名signWith 和加密encryptWith 不能同时使用
        ;
        /*
         * 7个标准声明，使用标准声明增强可读性
iss(Issuser)：代表这个JWT的签发主体；
sub(Subject)：代表这个JWT的主体，即它的所有人；
aud(Audience)：代表这个JWT的接收对象；
exp(Expiration time)：是一个时间戳，代表这个JWT的过期时间；
nbf(Not Before)：是一个时间戳，代表这个JWT生效的开始时间，意味着在这个时间之前验证JWT是会失败的；
iat(Issued at)：是一个时间戳，代表这个JWT的签发时间；
jti(JWT ID)：是JWT的唯一标识。
         */

        /*
        * 一个JWT payload可以是任何东西——可以用字节数组表示的任何东西，比如文本、图像、文档等等
        JwtBuilder支持两种不同的有效负载选项:
        content如果您希望有效负载是任意字节数组内容
        claims 如果您希望有效负载是JSON声明Object.
        * content和claims 不能同时使用。两者都用会导致compact()引发异常
        * content第一个参数是要设置为JWT有效负载的实际字节内容，第二个参数是IANA媒体类型的字符串标识符。
        * 对应解析：parseSignedClaims和parseSignedContent
        * */
        

    }
    

    
    public static Claims verify(String jwt,SecretKey key) {
         return Jwts.parser()
                 .clockSkewSeconds(5)//校验exp或者nbf时，考虑时钟偏差
                 //.json(new JacksonDeserializer(objectMapper))
                 .verifyWith(key)
                 .build()
                 .parseSignedClaims(jwt)
                 .getPayload();

    }

//    private static class NullValueSerializer extends StdSerializer<NullValue> {
//
//        private static final long serialVersionUID = 1999052150548658808L;
//        private final String classIdentifier;
//
//        /**
//         * @param classIdentifier can be {@literal null} and will be defaulted to {@code @class}.
//         */
//        NullValueSerializer(@Nullable String classIdentifier) {
//
//            super(NullValue.class);
//            this.classIdentifier = StringUtils.hasText(classIdentifier) ? classIdentifier : "@class";
//        }
//
//        /*
//         * (non-Javadoc)
//         * @see com.fasterxml.jackson.databind.ser.std.StdSerializer#serialize(java.lang.Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)
//         */
//        @Override
//        public void serialize(NullValue value, JsonGenerator jgen, SerializerProvider provider)
//                throws IOException {
//
//            jgen.writeStartObject();
//            jgen.writeStringField(classIdentifier, NullValue.class.getName());
//            jgen.writeEndObject();
//        }
//    }
}
